#pragma once
#include<unistd.h>
#include<iostream>
#include <sys/types.h>          
#include <sys/socket.h>
#include <sys/types.h>         
#include <sys/socket.h>
#include <netinet/in.h>
#include<cstring>
#include<vector>
#include<cerrno>
#include<functional>
#include"Log.hpp"
#include"Comm.hpp"
#include"nocopy.hpp"
#include"InetAddr.hpp"
#include"MyMutex.hpp"
#include"Threadpool.hpp"
#include"mythread.hpp"


const static uint16_t defaultport = 8080;
const static uint16_t defaultsize = 1024;
const static uint16_t defaultfd = -1;
using task_t = function<void()>;

class UdpSever:nocopy //防止拷贝，子类进行拷贝时会调用父类的拷贝构造函数，而父类nocopy的拷贝构造被dele掉了
{    
public:
    UdpSever(uint16_t port = defaultport):_port(port),_sockfd(defaultfd)
    {
        pthread_mutex_init(&_user_mutex,nullptr);
    }
    void Init()
    {
        //1、创建socket，创建文件细节
        _sockfd = socket(AF_INET,SOCK_DGRAM,0);
        if(_sockfd < 0)
        {
            lg.LogMessage(Fatal, "socket errr, %d : %s\n", errno, strerror(errno));
            exit(Socket_Err);
        }

        lg.LogMessage(Info, "socket success, sockfd: %d\n", _sockfd);

        //2、进行bind网络信息
        struct sockaddr_in local;
        bzero(&local,sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        local.sin_addr.s_addr = INADDR_ANY; //设置服务器ip为自动

        int n = ::bind(_sockfd,(const sockaddr*)&local,sizeof(local));
        if(n != 0)
        {
            lg.LogMessage(Fatal, "bind errr, %d : %s\n", errno, strerror(errno));
            exit(Bind_Err);
        }

        ThreadPool<task_t>::GetInstance()->Start(); //获取线程池单例并开始运行

    }
    void Route(int sock,const std::string& message)
    {
        //路由转发给所有用户
        LockGuard lockguard(&_user_mutex);
        for(auto &user : _online_user)
        {
            sendto(sock, message.c_str(), message.size(), 0, (struct sockaddr*)&user.GetAddr(), sizeof(user.GetAddr()));
        }
    }
    void AddOnlineUser(const InetAddr& addr)
    {
        LockGuard lockguard(&_user_mutex);
        for(auto &user : _online_user)
        {
            if(addr == user) return;
        }
        _online_user.push_back(addr);
    }
    void Start()
    {
        //服务器运行后，永不退出
        char buffer[defaultsize] = {0};
        while(true)
        {
            //接收消息
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            ssize_t n = recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(sockaddr*)&peer,&len);

            if(n > 0) //n为实际收到的字节数
            {
                //添加用户
                InetAddr addr(peer);
                AddOnlineUser(InetAddr(peer));
                buffer[n] = 0;
                std::string message = "[";
                message += addr.Ip();
                message += ":";
                message += std::to_string(addr.Port());
                message += "]# ";
                message += buffer;

                //处理消息,将消息给线程池的线程，转发给每个用户
                task_t task  = std::bind(&UdpSever::Route,this,_sockfd,message);

                ThreadPool<task_t>::GetInstance()->Push(task);
            }

        }
    }
    ~UdpSever()
    {
        pthread_mutex_destroy(&_user_mutex);
    }
private:
    uint16_t _port;
    int _sockfd;
    std::vector<InetAddr> _online_user; //多个线程要同时访问
    pthread_mutex_t _user_mutex;
};